package com.jerry.usbserial.util.task.usb2

import android.content.Context
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.Log
import com.jerry.usbserial.activity.UsbService
import com.jerry.usbserial.util.MenuItem
import com.jerry.usbserial.util.toHex
import java.io.BufferedWriter
import java.io.File
import java.io.FileOutputStream
import java.io.OutputStreamWriter
import java.util.*
import kotlin.concurrent.thread

/**
 * Created by dugang on 2020/7/14.
 */
class WaitSendData(val firmware: File? = null, val image: File? = null, val menu: List<MenuItem>? = null)

class SendItem(val step: Int, val data: ByteArray, val check: ByteArray? = null)

abstract class BaseTask(context: Context, private val mUsbService: UsbService, private val mWaitSendData: WaitSendData) : Thread() {
    private var mSendWriter: BufferedWriter
    private var mReceivedWriter: BufferedWriter

    private val cmdList = mutableListOf<SendItem>()
    private var mSendIndex = 0
    private var mHandler: Handler? = null

    private var mProgressListener: ((progress: Int) -> Unit)? = null
    private var mMessageListener: ((message: String) -> Unit)? = null

    @Volatile
    private var lastSend: SendItem = SendItem(0, byteArrayOf())


    init {
        val sendFile = File(context.getExternalFilesDir("logs"), "send.log")
        if (sendFile.exists()) sendFile.delete()
        mSendWriter = BufferedWriter(OutputStreamWriter(FileOutputStream(sendFile, true)))

        val receiveFile = File(context.getExternalFilesDir("logs"), "receive.log")
        if (receiveFile.exists()) receiveFile.delete()
        mReceivedWriter = BufferedWriter(OutputStreamWriter(FileOutputStream(receiveFile, true)))
    }

    fun addCmd(item: SendItem) {
        cmdList.add(item)
    }

    open fun firmwareData(file: File) {
        Log.d(TAG, "init firmwareData ")
    }

    open fun imageData(file: File) {
        Log.d(TAG, "inti imageData ")

    }

    open fun menuData(data: List<MenuItem>) {
        Log.d(TAG, "init menuData ")

    }


    override fun run() {
        super.run()
        mWaitSendData.firmware?.let {
            thread { firmwareData(it) }.join()
        }

        mWaitSendData.image?.let {
            thread { imageData(it) }.join()
        }

        mWaitSendData.menu?.let {
            thread { menuData(it) }.join()
        }

        Looper.prepare()
        val looper = Looper.myLooper()
        mHandler = object : Handler(looper!!) {
            override fun handleMessage(msg: Message) {
                super.handleMessage(msg)
                when (msg.what) {
                    WHAT_SEND -> {
                        lastSend = cmdList[msg.arg1]
                        mSendWriter.write("STEP：${lastSend.step} DATA：${lastSend.data.toHex().toUpperCase(Locale.getDefault())}\n")
                        mSendWriter.flush()
                        // todo 要打印的文字信息

                        mUsbService.write(lastSend.data)
                    }
                    WHAT_RECEIVE -> {
                        if (checkResult(msg.obj as ByteArray, lastSend)) {
                            // 如果有下一个数据,则继续发送, 否则结束
                            if (mSendIndex < cmdList.size) {
                                mSendIndex++
                                mProgressListener?.invoke(mSendIndex * 100 / cmdList.size)
                                obtainMessage(WHAT_SEND, mSendIndex, 0)
                            }
                        } else {
                            obtainMessage(WHAT_SEND, mSendIndex, 0)
                        }
                    }
                    WHAT_RETRY -> {
                        obtainMessage(WHAT_SEND, mSendIndex, 0)
                    }
                    WHAT_QUIT -> looper?.quitSafely()
                }
            }
        }
        Looper.loop()
    }

    fun handlerReceive(byteArray: ByteArray) {
        synchronized(lastSend) {
            mReceivedWriter.write("STEP: ${lastSend.step} DATA: ${lastSend.data.toHex().toUpperCase(Locale.getDefault())}\n")
            mReceivedWriter.flush()
            mHandler?.obtainMessage(WHAT_RECEIVE, byteArray)
        }
    }

    fun setOnProgressListener(func: (progress: Int) -> Unit) {
        mProgressListener = func
    }

    fun setOnMessageListener(func: (message: String) -> Unit) {
        mMessageListener = func
    }

    abstract fun checkResult(receive: ByteArray, lastSend: SendItem): Boolean

    abstract fun printMessage(lastSend: SendItem): String?

    companion object {
        private const val WHAT_QUIT = 0
        private const val WHAT_SEND = 1
        private const val WHAT_RECEIVE = 2
        private const val WHAT_RETRY = 3
        private const val TAG = "usb_update_task"
    }
}